package com.ardf.service.impl;

import com.ardf.common.EntityConstants;
import com.ardf.entity.Grade;
import com.ardf.entity.Group;
import com.ardf.entity.Project;
import com.ardf.entity.Rule;
import com.ardf.entity.dto.ProjectStartDto;
import com.ardf.mapper.GradeMapper;
import com.ardf.mapper.GroupMapper;
import com.ardf.mapper.ProjectMapper;
import com.ardf.service.IProjectService;
import com.ardf.service.IRuleService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ShiYunHao
 * @since 2025-01-06
 */
@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements IProjectService {

    private final GroupMapper groupMapper;
    private final ProjectMapper projectMapper;
    private final IRuleService ruleService;
    private final GradeMapper gradeMapper;

    public ProjectServiceImpl(GroupMapper groupMapper, ProjectMapper projectMapper, IRuleService ruleService,
                              GradeMapper gradeMapper) {
        this.groupMapper = groupMapper;
        this.projectMapper = projectMapper;
        this.ruleService = ruleService;
        this.gradeMapper = gradeMapper;
    }

    @Override
    @Transactional
    public void saveAll(List<Project> projects) {
        projectMapper.insert(projects);
        List<Project> projectList = projects.stream().map(project -> projectMapper.selectOne(new LambdaQueryWrapper<Project>()
                .eq(Project::getCompetitionId, project.getCompetitionId())
                .eq(Project::getType, project.getType())
                .eq(Project::getCategory, project.getCategory())
                .eq(Project::getFrequency, project.getFrequency()))).toList();
        List<Group> groupList = groupMapper.selectList(new LambdaQueryWrapper<Group>()
                .eq(Group::getCompetitionId, projects.get(0).getCompetitionId()));
        if (!groupList.isEmpty()) {
            List<Rule> rules = groupList.stream().map(group -> projectList.stream()
                            .filter(project -> !"公开组".equals(group.getName()) ||
                                    !EntityConstants.PROJECT_CATEGORY_RELAY.equals(project.getCategory()))
                            .map(project -> {
                                Rule rule = new Rule();
                                rule.setGroupId(group.getId());
                                rule.setProjectId(project.getId());
                                return rule;
                            }).toList())
                    .flatMap(List::stream)
                    .toList();
            ruleService.addByBatch(rules);
        }
    }

    @Override
    @Transactional
    public void deleteAll(List<Long> ids) {
        Long competitionId = projectMapper.selectById(ids.get(0)).getCompetitionId();
        Long count = groupMapper.selectCount(new LambdaQueryWrapper<Group>()
                .eq(Group::getCompetitionId, competitionId));
        if (count != null && count != 0) {
            List<Long> ruleIds = ruleService.listObjs(new LambdaQueryWrapper<Rule>().select(Rule::getId)
                    .in(Rule::getProjectId, ids));
            if (ruleIds != null && !ruleIds.isEmpty()) {
                ruleService.deleteByBatch(ruleIds);
            }
        }
        projectMapper.deleteByIds(ids);
    }

    @Override
    @Transactional
    public void deleteOne(Long id) {
        Long competitionId = projectMapper.selectById(id).getCompetitionId();
        Long count = groupMapper.selectCount(new LambdaQueryWrapper<Group>()
                .eq(Group::getCompetitionId, competitionId));
        if (count != null && count != 0) {
            List<Long> ruleIds = ruleService.listObjs(new LambdaQueryWrapper<Rule>().select(Rule::getId)
                    .eq(Rule::getProjectId, id));
            if (ruleIds != null && !ruleIds.isEmpty()) {
                ruleService.deleteByBatch(ruleIds);
            }
        }
        projectMapper.deleteById(id);
    }

    @Override
    public ProjectStartDto getRecentProject(Long competitionId) {
        LocalDateTime nowDateTime = LocalDateTime.now();
//        System.out.println(nowDateTime);
        Long groupCount = groupMapper.selectCount(new LambdaQueryWrapper<Group>()
                .eq(Group::getCompetitionId, competitionId));
        if (groupCount == null || groupCount == 0) {
            return new ProjectStartDto();
        }
        Project recentProject = projectMapper.getRecentProject(competitionId, nowDateTime);
        if (recentProject == null) {
            return new ProjectStartDto();
        }

        String projectName = EntityConstants.PROJECT_TYPE_STRING_MAP.get(recentProject.getType()) +
                EntityConstants.PROJECT_FREQUENCY_STRING_MAP.get(recentProject.getFrequency()) +
                EntityConstants.PROJECT_CATEGORY_STRING_MAP.get(recentProject.getCategory());

        ProjectStartDto projectStartDto = new ProjectStartDto();
        projectStartDto.setProjectId(recentProject.getId());
        projectStartDto.setProjectName(projectName);
        projectStartDto.setStartTime(recentProject.getStartTime());
        projectStartDto.setIsRelay(EntityConstants.PROJECT_CATEGORY_RELAY.equals(recentProject.getCategory()));
        Long total = gradeMapper.selectCount(new LambdaQueryWrapper<Grade>()
                .eq(Grade::getProjectId, recentProject.getId()));
        projectStartDto.setTotal(total);
        Long hasT = gradeMapper.selectCount(new LambdaQueryWrapper<Grade>()
                .eq(Grade::getProjectId, recentProject.getId())
                .and(gradeLambdaQueryWrapper -> gradeLambdaQueryWrapper.isNotNull(Grade::getRoute)
                        .or().isNotNull(Grade::getTime)));
        projectStartDto.setHasTerminal(hasT);
        if (total != null) {
            if (hasT != null) {
                projectStartDto.setUnTerminal(total - hasT);
            } else {
                projectStartDto.setUnTerminal(total);
            }
        }
        return projectStartDto;
    }

    @Override
    public Project getEarliestProject(Long competitionId) {
        return projectMapper.selectOne(new LambdaQueryWrapper<Project>().eq(Project::getCompetitionId,competitionId).orderByAsc(Project::getStartTime).last("limit 1"));
    }


    @Override
    public String checkReasonableProTime(Long competitionId) {
        //按赛事id查询所有的项目，并且按照开始时间排序
        List<Project> projects=projectMapper.selectList(new LambdaQueryWrapper<Project>().eq(Project::getCompetitionId,competitionId).orderByAsc(Project::getStartTime));

        for (int i = 1; i < projects.size(); i++) {

            ZonedDateTime dateTime1 = projects.get(i-1).getStartTime().atZone(ZoneId.systemDefault());
            ZonedDateTime dateTime2 = projects.get(i).getStartTime().atZone(ZoneId.systemDefault());

            // 从ZonedDateTime中获取Instant对象
            Instant instant1 = dateTime1.toInstant();
            Instant instant2 = dateTime2.toInstant();

            // 获取自1970年1月1日00:00:00 UTC起的秒数
            long seconds1 = instant1.getEpochSecond();
            long seconds2 = instant2.getEpochSecond();

            //小于1h
            if (seconds2-seconds1<7200){
                String project1Name = EntityConstants.PROJECT_TYPE_STRING_MAP.get(projects.get(i-1).getType()) +
                        EntityConstants.PROJECT_FREQUENCY_STRING_MAP.get(projects.get(i-1).getFrequency()) +
                        EntityConstants.PROJECT_CATEGORY_STRING_MAP.get(projects.get(i-1).getCategory());
                String project2Name = EntityConstants.PROJECT_TYPE_STRING_MAP.get(projects.get(i).getType()) +
                        EntityConstants.PROJECT_FREQUENCY_STRING_MAP.get(projects.get(i).getFrequency()) +
                        EntityConstants.PROJECT_CATEGORY_STRING_MAP.get(projects.get(i).getCategory());
                return "“"+project1Name+"” 和 “"+project2Name+"” 时间设置不合理!!! 时间间隔少于2小时 !!!!";
            }
        }
        return "合理";
    }
}
